package impl

import (
	"context"
	"encoding/base64"
	"errors"
	"gitee.com/hexug/go-tools/logger"
	"gitee.com/hexug/kube-sync/apps/cleandata"
	"gitee.com/hexug/kube-sync/apps/resource"
	appsv1 "k8s.io/api/apps/v1"
	batchv1 "k8s.io/api/batch/v1"
	batchv1beta1 "k8s.io/api/batch/v1beta1"
	"os"
)

// CleanDeployment 根据配置清理 Deployment 对象中的字段，返回清理后的 Deployment 信息。
// 参数:
//   - ctx: 上下文，用于控制请求的生命周期。
//   - req: 包含需要清理的 Deployment 数据的请求对象。
//
// 返回值:
//   - *cleandata.CleanDeploymentResponse: 清理后的 Deployment 信息响应对象。
//   - error: 如果处理过程中发生错误，则返回相应的错误信息。
func (s *svcImpl) CleanDeployment(ctx context.Context, req *cleandata.CleanDeploymentRequest) (*cleandata.CleanDeploymentResponse, error) {
	if s.config.Deployment == nil {
		logger.L().Error("Deployment not configured")
		return nil, errors.New("deployment not configured")
	}

	result := cleandata.NewCleanDeploymentResponse()

	// 遍历每个命名空间的Deployment
	for ns, deps := range req.Deployments {
		infoList := make([]*cleandata.DeploymentInfo, 0, len(deps))

		for _, dep := range deps {
			if dep == nil {
				continue // 跳过空指针，增强健壮性
			}

			// 将 Deployment 对象转换为 map 结构以便处理
			depStr, err := cleandata.ObjToMap(dep)
			if err != nil {
				logger.L().Errorw("CleanDeployment error", "error", err.Error(), "namespace", ns, "deployment", dep.Name)
				return nil, err
			}

			// 添加 GroupVersionKind 信息到 map 中
			ds := cleandata.WithGVK(depStr, dep)

			// 应用过滤规则
			filteredMap := cleandata.ApplyRules(ds, s.config.Deployment)

			//// 将过滤后的map转换回JSON字节
			//data, err := yamlv3.Marshal(filteredMap)
			//if err != nil {
			//	return nil, fmt.Errorf("序列化Deployment %s 失败: %v", dep.Name, err)
			//}

			// 创建DeploymentInfo并添加到结果列表
			infoList = append(infoList, cleandata.NewDeploymentInfo(dep.Name, ns, filteredMap))
		}

		if len(infoList) > 0 {
			//result.Items[ns] = infoList
			result.Add(ns, infoList)
		}
	}

	return result, nil
}
func (s *svcImpl) CleanWorkload(ctx context.Context, req *resource.ListWorkloadRespone) (*cleandata.CleanWorkloadResponse, error) {
	if len(req.Items) == 0 {
		logger.L().Error("无资源需要处理")
		os.Exit(0)
	}
	rep := cleandata.NewCleanWorkloadResponse()
	for key, item := range req.Items {
		var name string
		var objMap map[string]any
		switch item.WorkloadType {
		case "Deployment":
			dep, ok := item.Workload.(*appsv1.Deployment)
			if !ok {
				continue
			}
			// 将 Deployment 对象转换为 map 结构以便处理
			depStr, err := cleandata.ObjToMap(dep)
			if err != nil {
				logger.L().Errorw("CleanDeployment error", "error", err.Error(), "namespace", dep.Namespace, "Deployment", dep.Name)
				return nil, err
			}
			name = dep.Name
			// 添加 GroupVersionKind 信息到 map 中
			ds := cleandata.WithGVK(depStr, dep)
			objMap = cleandata.ApplyRules(ds, s.config.Deployment)
		case "StatefulSet":
			dep, ok := item.Workload.(*appsv1.StatefulSet)
			if !ok {
				continue
			}
			// 将 Deployment 对象转换为 map 结构以便处理
			depStr, err := cleandata.ObjToMap(dep)
			if err != nil {
				logger.L().Errorw("CleanStatefulSet error", "error", err.Error(), "namespace", dep.Namespace, "StatefulSet", dep.Name)
				return nil, err
			}
			name = dep.Name
			// 添加 GroupVersionKind 信息到 map 中
			ds := cleandata.WithGVK(depStr, dep)
			objMap = cleandata.ApplyRules(ds, s.config.StatefulSet)
		case "DaemonSet":
			dep, ok := item.Workload.(*appsv1.DaemonSet)
			if !ok {
				continue
			}
			// 将 Deployment 对象转换为 map 结构以便处理
			depStr, err := cleandata.ObjToMap(dep)
			if err != nil {
				logger.L().Errorw("CleanDaemonSet error", "error", err.Error(), "namespace", dep.Namespace, "DaemonSet", dep.Name)
				return nil, err
			}
			name = dep.Name
			// 添加 GroupVersionKind 信息到 map 中
			ds := cleandata.WithGVK(depStr, dep)
			objMap = cleandata.ApplyRules(ds, s.config.DaemonSet)
		case "Job":
			dep, ok := item.Workload.(*batchv1.Job)
			if !ok {
				continue
			}
			// 将 Deployment 对象转换为 map 结构以便处理
			depStr, err := cleandata.ObjToMap(dep)
			if err != nil {
				logger.L().Errorw("CleanJob error", "error", err.Error(), "namespace", dep.Namespace, "Job", dep.Name)
				return nil, err
			}
			name = dep.Name
			// 添加 GroupVersionKind 信息到 map 中
			ds := cleandata.WithGVK(depStr, dep)
			objMap = cleandata.ApplyRules(ds, s.config.Job)
		case "CronJob":
			dep, ok := item.Workload.(*batchv1.CronJob)
			if !ok {
				depb, ok := item.Workload.(*batchv1beta1.CronJob)
				if !ok {
					continue
				}
				// 将 Deployment 对象转换为 map 结构以便处理
				depstr, err := cleandata.ObjToMap(depb)
				if err != nil {
					logger.L().Errorw("CleanCronJob error", "error", err.Error(), "namespace", dep.Namespace, "CronJob", dep.Name)
					return nil, err
				}
				name = depb.Name
				// 添加 GroupVersionKind 信息到 map 中
				ds := cleandata.WithGVK(depstr, depb)
				objMap = cleandata.ApplyRules(ds, s.config.CronJob)

			} else {
				// 将 Deployment 对象转换为 map 结构以便处理
				depstr, err := cleandata.ObjToMap(dep)
				if err != nil {
					logger.L().Errorw("CleanCronJob error", "error", err.Error(), "namespace", dep.Namespace, "CronJob", dep.Name)
					return nil, err
				}
				name = dep.Name
				// 添加 GroupVersionKind 信息到 map 中
				ds := cleandata.WithGVK(depstr, dep)
				objMap = cleandata.ApplyRules(ds, s.config.CronJob)
			}

		default:
			continue
		}
		// 特殊处理：如果serviceAccount或serviceAccountName为default，则移除
		removeDefaultServiceAccountFields(objMap)
		rep.Add(key, cleandata.NewCleanWorkloadInfo(name, item.Namespace, item.WorkloadType, objMap))
	}
	return rep, nil
}

// removeDefaultServiceAccountFields 移除serviceAccount和serviceAccountName字段，如果它们的值为"default"
func removeDefaultServiceAccountFields(objMap map[string]any) {
	if objMap == nil {
		return
	}

	// 检查spec字段是否存在
	spec, ok := objMap["spec"].(map[string]any)
	if !ok {
		return
	}

	// 检查直接位于spec下的serviceAccount字段
	if serviceAccount, ok := spec["serviceAccount"].(string); ok && serviceAccount == "default" {
		delete(spec, "serviceAccount")
	}

	// 检查直接位于spec下的serviceAccountName字段
	if serviceAccountName, ok := spec["serviceAccountName"].(string); ok && serviceAccountName == "default" {
		delete(spec, "serviceAccountName")
	}

	// 检查spec.template.spec下的serviceAccountName字段（适用于Deployment、StatefulSet、DaemonSet等）
	if template, ok := spec["template"].(map[string]any); ok {
		if templateSpec, ok := template["spec"].(map[string]any); ok {
			if serviceAccountName, ok := templateSpec["serviceAccountName"].(string); ok && serviceAccountName == "default" {
				delete(templateSpec, "serviceAccountName")
			}
			// 检查spec.template.spec下的serviceAccount字段
			if serviceAccount, ok := templateSpec["serviceAccount"].(string); ok && serviceAccount == "default" {
				delete(templateSpec, "serviceAccount")
			}
		}
	}
}

//
//func (s *svcImpl) CleanStatefulSet(ctx context.Context, req *cleandata.CleanStatefulSetRequest) (*cleandata.CleanStatefulSetResponse, error) {
//	//TODO implement me
//	panic("implement me")
//}
//
//func (s *svcImpl) CleanDaemonSet(ctx context.Context, req *cleandata.CleanDaemonSetRequest) (*cleandata.CleanDaemonSetResponse, error) {
//	//TODO implement me
//	panic("implement me")
//}
//
//func (s *svcImpl) CleanJob(ctx context.Context, req *cleandata.CleanJobRequest) (*cleandata.CleanJobResponse, error) {
//	//TODO implement me
//	panic("implement me")
//}
//
//func (s *svcImpl) CleanCronJob(ctx context.Context, req *cleandata.CleanCronJobRequest) (*cleandata.CleanCronJobResponse, error) {
//	//TODO implement me
//	panic("implement me")
//}

func (s *svcImpl) CleanService(ctx context.Context, req *cleandata.CleanServiceRequest) (*cleandata.CleanServiceResponse, error) {
	result := cleandata.NewCleanServiceResponse()
	if err := req.Validate(); err != nil {
		logger.L().Infow("CleanService warn", "warn", err.Error())
		return result, nil
	}

	for _, svcInfo := range req.Services {
		if svcInfo == nil {
			continue
		}
		// 将 Deployment 对象转换为 map 结构以便处理
		svcStr, err := cleandata.ObjToMap(svcInfo.Services)
		if err != nil {
			logger.L().Errorw("CleanService error", "error", err.Error(), "namespace", svcInfo.Namespace, svcInfo.WorkloadType, svcInfo.Workload)
			return nil, err
		}
		// 添加 GroupVersionKind 信息到 map 中
		sv := cleandata.WithGVK(svcStr, svcInfo.Services)

		// 应用过滤规则
		filteredMap := cleandata.ApplyRules(sv, s.config.Service)

		// 将过滤后的map转换回JSON字节
		//data, err := yamlv3.Marshal(filteredMap)
		//if err != nil {
		//	return nil, fmt.Errorf("序列化Service %s 失败: %v", svcInfo.Services.Name, err)
		//}
		si := cleandata.NewServiceInfo(svcInfo.Workload, svcInfo.Namespace, filteredMap)
		result.Add(svcInfo.Workload, svcInfo.Namespace, svcInfo.WorkloadType, si)
	}
	return result, nil
}

func (s *svcImpl) CleanConfigMap(ctx context.Context, req *cleandata.CleanConfigMapRequest) (*cleandata.CleanConfigMapResponse, error) {
	result := cleandata.NewCleanConfigMapResponse()
	if err := req.Validate(); err != nil {
		logger.L().Infow("CleanConfigMap warn", "warn", err.Error())
		return result, nil
	}
	for _, cmInfo := range req.ConfigMaps {
		if cmInfo == nil {
			continue
		}
		for _, cm := range cmInfo.ConfigMaps {
			// 将 Configmap 对象转换为 map 结构以便处理
			cmStr, err := cleandata.ObjToMap(cm)
			if err != nil {
				logger.L().Errorw("CleanConfigMap error", "error", err.Error(), "namespace", cmInfo.Namespace, cmInfo.WorkloadType, cmInfo.Workload)
				return nil, err
			}
			// 添加 GroupVersionKind 信息到 map 中
			cv := cleandata.WithGVK(cmStr, cm)

			// 应用过滤规则
			filteredMap := cleandata.ApplyRules(cv, s.config.ConfigMap)

			// 将过滤后的map转换回JSON字节
			//data, err := yamlv3.Marshal(filteredMap)
			//if err != nil {
			//	return nil, fmt.Errorf("序列化Service %s 失败: %v", svcInfo.Services.Name, err)
			//}
			ci := cleandata.NewConfigmapInfo(cmInfo.Workload, cmInfo.Namespace, filteredMap, cm.Name)
			result.Add(cmInfo.Workload, cmInfo.Namespace, cmInfo.WorkloadType, ci)
		}

	}
	return result, nil

}

func (s *svcImpl) CleanRBAC(ctx context.Context, req *resource.FromWorkloadGetRBACResponse) (*cleandata.CleanRBACResponse, error) {
	result := cleandata.NewCleanRBACResponse()
	if req == nil {
		return nil, errors.New("request is nil")
	}
	for key, rbacInfo := range req.Items {
		if rbacInfo == nil {
			continue
		}
		rbacCore := cleandata.NewDefaultRBACCore()
		logger.L().Debugw("开始处理ServiceAccount", "key", key)
		// 将 Configmap 对象转换为 map 结构以便处理
		saStr, err := cleandata.ObjToMap(rbacInfo.ServiceAccount)
		if err != nil {
			logger.L().Errorw("ServiceAccount error", "error", err.Error(), "namespace", rbacInfo.ServiceAccount.Namespace, "ServiceAccount", rbacInfo.ServiceAccount.Name)
			return nil, err
		}
		// 添加 GroupVersionKind 信息到 map 中
		sa := cleandata.WithGVK(saStr, rbacInfo.ServiceAccount)

		// 应用过滤规则
		filteredMapSA := cleandata.ApplyRules(sa, s.config.ServiceAccount)
		rbacCore.AddServiceAccount(filteredMapSA)
		logger.L().Debugw("开始处理Role", "key", key)
		for _, role := range rbacInfo.Roles {
			// 将 Role 对象转换为 map 结构以便处理
			roleStr, err := cleandata.ObjToMap(role)
			if err != nil {
				logger.L().Errorw("Role error", "error", err.Error(), "namespace", role.Namespace, "Role", role.Name)
				continue
			}
			// 添加 GroupVersionKind 信息到 map 中
			ro := cleandata.WithGVK(roleStr, role)

			// 应用过滤规则
			filteredMapRole := cleandata.ApplyRules(ro, s.config.Role)
			rbacCore.AddRole(filteredMapRole)
		}
		logger.L().Debugw("开始处理RoleBinding", "key", key)
		for _, roleBinding := range rbacInfo.RoleBindings {
			// 将 RoleBinding 对象转换为 map 结构以便处理
			roleBindingStr, err := cleandata.ObjToMap(roleBinding)
			if err != nil {
				logger.L().Errorw("RoleBinding error", "error", err.Error(), "namespace", roleBinding.Namespace, "RoleBinding", roleBinding.Name)
				continue
			}
			// 添加 GroupVersionKind 信息到 map 中
			rb := cleandata.WithGVK(roleBindingStr, roleBinding)
			// 应用过滤规则
			filteredMapRoleBinding := cleandata.ApplyRules(rb, s.config.RoleBindings)
			rbacCore.AddRoleBinding(filteredMapRoleBinding)
		}
		logger.L().Debugw("开始处理ClusterRole", "key", key)
		for _, crole := range rbacInfo.ClusterRoles {
			// 将 ClusterRole 对象转换为 map 结构以便处理
			croleStr, err := cleandata.ObjToMap(crole)
			if err != nil {
				logger.L().Errorw("ClusterRole error", "error", err.Error(), "ClusterRole", crole.Name)
				continue
			}
			// 添加 GroupVersionKind 信息到 map 中
			cr := cleandata.WithGVK(croleStr, crole)
			// 应用过滤规则
			filteredMapClusterRole := cleandata.ApplyRules(cr, s.config.ClusterRole)
			rbacCore.AddClusterRole(filteredMapClusterRole)
		}
		logger.L().Debugw("开始处理ClusterRoleBinding", "key", key)
		for _, croleBinding := range rbacInfo.ClusterRBs {
			// 将 ClusterRoleBinding 对象转换为 map 结构以便处理
			croleBindingStr, err := cleandata.ObjToMap(croleBinding)
			if err != nil {
				logger.L().Errorw("ClusterRoleBinding error", "error", err.Error(), "ClusterRoleBinding", croleBinding.Name)
				continue
			}
			// 添加 GroupVersionKind 信息到 map 中
			crb := cleandata.WithGVK(croleBindingStr, croleBinding)
			// 应用过滤规则
			filteredMapClusterRoleBinding := cleandata.ApplyRules(crb, s.config.ClusterRoleBindings)
			rbacCore.AddClusterRoleBinding(filteredMapClusterRoleBinding)
		}
		result.Add(key, rbacCore)
	}
	return result, nil
}

func (s *svcImpl) CleanPvPvc(ctx context.Context, req *resource.FromWorkloadGetPVPVCResponse) (*cleandata.CleanPvPvcResponse, error) {
	if req == nil {
		return nil, errors.New("request is nil")
	}
	results := cleandata.NewCleanPvPvcResponse()
	for key, wkInfo := range req.Items {
		if wkInfo == nil {
			continue
		}
		pvPvc := cleandata.NewDefaultPvPvcCore()
		logger.L().Debugw("开始处理PV", "key", key)
		for _, pv := range wkInfo.PVs {
			pvStr, err := cleandata.ObjToMap(pv)
			if err != nil {
				logger.L().Errorw("PV error", "error", err.Error(), "namespace", pv.Namespace, "PV", pv.Name)
				continue
			}
			p := cleandata.WithGVK(pvStr, pv)
			filteredMapPV := cleandata.ApplyRules(p, s.config.PV)
			pvPvc.AddPV(filteredMapPV)
		}
		logger.L().Debugw("开始处理PVC", "key", key)
		for _, pvc := range wkInfo.PVCs {
			pvcStr, err := cleandata.ObjToMap(pvc)
			if err != nil {
				logger.L().Errorw("PVC error", "error", err.Error(), "namespace", pvc.Namespace, "PVC", pvc.Name)
				continue
			}
			p := cleandata.WithGVK(pvcStr, pvc)
			filteredMapPVC := cleandata.ApplyRules(p, s.config.PVC)
			pvPvc.AddPVC(filteredMapPVC)
		}
		results.Add(key, pvPvc)
	}
	return results, nil
}

func (s *svcImpl) CleanSecret(ctx context.Context, req *resource.FromWorkloadGetSecretResponse) (*cleandata.CleanSecretResponse, error) {
	if req == nil {
		return nil, errors.New("request is nil")
	}
	results := cleandata.NewCleanSecretResponse()
	for key, scCore := range req.Items {
		if scCore == nil {
			continue
		}
		score := cleandata.NewDefaultSecretCore(scCore.Namespace)
		logger.L().Debugw("开始处理Secret", "key", key)
		for _, sc := range scCore.Secrets {
			pvStr, err := cleandata.ObjToMap(sc)
			if err != nil {
				logger.L().Errorw("PV error", "error", err.Error(), "namespace", sc.Namespace, "PV", sc.Name)
				continue
			}
			p := cleandata.WithGVK(pvStr, sc)
			data := make(map[string]string)
			for k, v := range sc.Data {
				data[k] = base64.StdEncoding.EncodeToString(v)
			}
			p["data"] = data
			filteredMapPV := cleandata.ApplyRules(p, s.config.Secret)
			score.AddSecret(filteredMapPV)
		}
		if len(scCore.Secrets) > 0 {
			results.Add(key, score)
		}
	}
	return results, nil
}
